package CTCOffice;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.Queue;

import CTCOffice.Schedule.Destination;
import TrackModel.StationBlock;
import TrainModel.TrainModel;
import Utilities.Database;
import Utilities.Database.DBEntry;
import application.Main;


/**
 * CTCOffice is a class designed to represent the back-end functionality to the Main UI for the OCSD Train Controller.
 * It will provided many interfaces, such as one to pipe data between the various modules, another to route the trains
 * within the system to conform to the users destination requests and accommodate alternate track conditions, and finally
 * the ability to schedule the trains once the route is created to ensure a safe operating environment.
 * <p>
 * The default constructor will initialize the system to specification, and ensure the boot was a success so that the system can
 * function properly. Additional overloaded constructors may be added later to accommodate a system reboot, where some of the states
 * of the system are already known. Data recovery/redundancy will be explored.
 * 
 * @author Mike Hearing
 * 
 * @see Router
 * @see Scheduler
 */
public class CTCOffice {
	private int iTrainCount;
	public Database trainLog;
	private Scheduler scheduler;
	public Queue<String> messages;
	
	public boolean bMBOEnabled;

	/**
	 * Creates a CTCOffice based on the default configuration of an empty system. All of the internal components will be initialized,
	 * followed by the external modules, which will be called through static methods which belong to the GUI.  The former serves a 
	 * two-fold purpose of isolating the CTCOffice from the rest of the system, and visa versa, which prevents the propagation of errors
	 * from the top level down to the bottom level controllers and modules. Secondly, to maintain the layered architecture of the system.
	 */
	public CTCOffice() {
		Main.log.write("CTCOffice: Initializing...");

		iTrainCount = 0;
		bMBOEnabled = true;

		messages = new LinkedList<String>();
		scheduler = new Scheduler();
		trainLog = new Database("ID","LINE","ROUTE","DESTINATION","SCHEDULE");

		Main.log.write("CTCOffice: Completed Initialization.");
	}
	
	public void tick() {
		//Clears the track controller message queue
		this.messages.clear();
		//Dispatch trains on the minute
		Date d = new Date(Main.sysTime);
		SimpleDateFormat f = new SimpleDateFormat("ss");
		if(f.format(d) == "00") {
			f= new SimpleDateFormat("kk:mm");
			dispatchTrains(f.format(d));
		}
		// evaluate system (determine if rescheduling needs to occur)
		//scheduler.update();
	}
	
	/**
	 *
	 *
	 *	@param n Name of the train
	 *	@param l Line color of the train
	 *	@param end Destination of the train
	 */
	public void addTrain(String line, String end, String aTime) {
		//Create the train object
		//Main.trainModelList.add(new TrainModel(iTrainCount, Main.lTick));
		TrainModel t = Main.trackModel.yard.createTrain(iTrainCount, Main.lTick);
		Main.trackModel.yard.sendTrain(t, line);

		Main.log.write("CTCOffice: Create train command dispatched to the yard.");
		//Gets the end
		StationBlock endBlock = Main.trackModel.getLine(line).getStations().get(0);
		for(StationBlock s : Main.trackModel.getLine(line).getStations()) {
			if(s.getStationName() == end) {
				endBlock = s;
				break;
			}
		}

		//Route the train
		//ArrayList<Integer> r = Router.route(line, ((StationBlock)Main.trackModel.yard.getNextStation(line)), endBlock);
		ArrayList<StationBlock> r = Router.getRoute(line, ((StationBlock)Main.trackModel.yard.getNextStation(line)).getStationName(), end);

		String output = " ";
		for(StationBlock s : r)
			output += s.getBlockID() + ",";
		output = output.substring(0, output.length() - 1);
		System.out.println(output);

		Main.log.write("CTCOffice: Route(" + r.get(0).getStationName() + "," + r.get(r.size() - 1).getStationName() + ") = [" + output + "]");

		//Schedule the train
		scheduler.addScheudle(iTrainCount, r, aTime);

		//Add to the log
		trainLog.addEntry(iTrainCount, iTrainCount, line, r, end, aTime);
		Main.log.write("CTCOffice: Train ID" + (iTrainCount) + " has been registered.");
		iTrainCount++;
	}
	
	public void dispatchTrains(String time) {
		ArrayList<DBEntry> results = trainLog.getEntriesByHeader("LINE", "Green");
		for(DBEntry entry : results) {
			Destination d  = ((Schedule)entry.getData(trainLog.getHeaderID("SCHEDULE"))).getStations().get(0);
			SimpleDateFormat f = new SimpleDateFormat("kk:mm");
			if(d.getArrival() == f.format(Main.sysTime)) {
				Main.trackModel.yard.sendTrain(Main.trainModelList.get(((int)entry.getData(trainLog.getHeaderID("ID")))), ((String)entry.getData(trainLog.getHeaderID("LINE"))));
			}
		}
	}

	public void scheduleTrain(int tid) {

	}
	
	public void setSwitch(int s) { 
		String msg = "0";
		
		
		
		this.messages.add(msg);
	}

	public void setSpeed(int tid, double s) {
		String msg = "1";
		if(tid <= 9)
			msg += "0";
		msg += String.valueOf(tid) + s;
		this.messages.add(msg);

		Main.log.write("CTCOffice: Set Speed " + s);
	}

	public void setAuthority(int tid, int a) {
		String msg = "2";
		if(tid <= 9)
			msg += "0";
		msg += String.valueOf(tid) + a;
		this.messages.add(msg);

		Main.log.write("CTCOffice: Set Authority " + a);
	}
	
	public int getTrainCount() {
		return iTrainCount;
	}
}